package co.edu.usbcali.unidades.presentation.backingBeans;

import co.edu.usbcali.unidades.modelo.Pais;
import co.edu.usbcali.unidades.utilities.FacesUtils;
import co.edu.usbcali.unidades.modelo.Ciudad;
import co.edu.usbcali.unidades.exceptions.*;
import co.edu.usbcali.unidades.modelo.*;
import co.edu.usbcali.unidades.modelo.dto.CiudadDTO;
import co.edu.usbcali.unidades.presentation.businessDelegate.BusinessDelegatorView;
import co.edu.usbcali.unidades.utilities.*;

import com.icesoft.faces.async.render.RenderManager;
import com.icesoft.faces.async.render.Renderable;
import com.icesoft.faces.component.ext.HtmlCommandButton;
import com.icesoft.faces.component.ext.HtmlInputText;
import com.icesoft.faces.component.ext.HtmlSelectOneMenu;
import com.icesoft.faces.component.ext.RowSelectorEvent;
import com.icesoft.faces.component.selectinputdate.SelectInputDate;
import com.icesoft.faces.context.DisposableBean;
import com.icesoft.faces.webapp.xmlhttp.FatalRenderingException;
import com.icesoft.faces.webapp.xmlhttp.PersistentFacesState;
import com.icesoft.faces.webapp.xmlhttp.RenderingException;
import com.icesoft.faces.webapp.xmlhttp.TransientRenderingException;

import java.math.BigDecimal;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.TimeZone;
import java.util.Vector;

import javax.faces.event.ValueChangeEvent;
import javax.faces.model.DataModel;
import javax.faces.model.SelectItem;


/**
*
*
* @author Zathura Code Generator http://code.google.com/p/zathura
*
*/
public class CiudadView extends DataSource implements Renderable,
    DisposableBean {
	private HtmlInputText txtCiuNombre;
	private HtmlInputText txtCiuCodigo;
	private HtmlCommandButton btnSave;
	private HtmlCommandButton btnModify;
	private HtmlCommandButton btnDelete;
	private HtmlCommandButton btnClear;
	private boolean renderDataTable;
	private boolean flag = true;
	private RenderManager renderManager;
	private PersistentFacesState state = PersistentFacesState.getInstance();
	private List<Ciudad> ciudad;
	private List<CiudadDTO> ciudadDTO;
	
	private boolean popupPais=false;
	private List<Pais> list_paises = new ArrayList<Pais>();
	
	private HtmlInputText txtPaiNombre;
	private HtmlInputText txtPaiNombreBusqueda;
	
	

    public CiudadView() {
        super("");
    }

    public String action_clear() {
		txtCiuNombre.setValue(null);
		txtPaiNombre.setValue("");		
		return "";
	}

    public String action_save() {
    	
		try {
			if (txtPaiNombre.getValue()==null){
				throw new Exception("Ingrese un país");
			}
			String paiCodigo=BusinessDelegatorView.getPaisPorNombre(txtPaiNombre.getValue().toString()).getPaiCodigo();			
			BusinessDelegatorView.saveCiudad(null, txtCiuNombre.getValue().toString().trim().toUpperCase(), "1", paiCodigo);
			flag=true;
			renderManager.getOnDemandRenderer("CiudadView").requestRender();
			FacesUtils.addInfoMessage(ZMessManager.ENTITY_SUCCESFULLYSAVED);
			action_clear();
		} catch (Exception e) {
			FacesUtils.addErrorMessage(e.getMessage());
		}
		return "";
	}

    public String action_delete() {
        try {
            BusinessDelegatorView.deleteCiudad(FacesUtils.checkString(
                    txtCiuCodigo));
            FacesUtils.addInfoMessage(ZMessManager.ENTITY_SUCCESFULLYDELETED);
            action_clear();
        } catch (Exception e) {
            FacesUtils.addErrorMessage(e.getMessage());
        }

        return "";
    }

    public String action_modify() {
		try {
			String paiCodigo=BusinessDelegatorView.getPaisPorNombre(txtPaiNombre.getValue().toString()).getPaiCodigo();
			BusinessDelegatorView.updateCiudad(null, FacesUtils
					.checkString(txtCiuNombre).toUpperCase().trim(), "1", paiCodigo);
			FacesUtils.addInfoMessage(ZMessManager.ENTITY_SUCCESFULLYMODIFIED);
			action_clear();
		} catch (Exception e) {
			FacesUtils.addErrorMessage(e.getMessage());
		}

		return "";
	}

    public String action_modifyWitDTO(String ciuCodigo, String ciuNombre,
        String estCodigo_Estado, String paiCodigo_Pais)
        throws Exception {
        try {
            BusinessDelegatorView.updateCiudad(ciuCodigo, ciuNombre,
                estCodigo_Estado, paiCodigo_Pais);
            renderManager.getOnDemandRenderer("CiudadView").requestRender();
            FacesUtils.addInfoMessage(ZMessManager.ENTITY_SUCCESFULLYMODIFIED);
        } catch (Exception e) {
            FacesUtils.addErrorMessage(e.getMessage());
            throw e;
        }

        return "";
    }

    public List<Ciudad> getCiudad() {
        if (flag) {
            try {
                ciudad = BusinessDelegatorView.getCiudad();
                flag = false;
            } catch (Exception e) {
                flag = true;
                FacesUtils.addErrorMessage(e.getMessage());
            }
        }

        return ciudad;
    }

    public boolean isFlag() {
        return flag;
    }

    public void setCiudad(List<Ciudad> ciudad) {
        this.ciudad = ciudad;
    }

    public boolean isRenderDataTable() {
        try {
            if (flag) {
                if (BusinessDelegatorView.findTotalNumberCiudad() > 0) {
                    renderDataTable = true;
                } else {
                    renderDataTable = false;
                }
            }

            flag = false;
        } catch (Exception e) {
            renderDataTable = false;
            e.printStackTrace();
        }

        return renderDataTable;
    }

    public DataModel getData() {
        state = PersistentFacesState.getInstance();

        if (onePageDataModel == null) {
            onePageDataModel = new LocalDataModel(pageSize);
        }

        return onePageDataModel;
    }

    /**
    * This is where the Object data is retrieved from the database and
    * returned as a list of objects for display in the UI.
    */
    private DataPage<Ciudad> getDataPage(int startRow, int pageSize) {
        // Retrieve the total number of objects from the database.  This
        // number is required by the DataPage object so the paginator will know
        // the relative location of the page data.
        int totalNumberCiudad = 0;

        try {
            totalNumberCiudad = BusinessDelegatorView.findTotalNumberCiudad()
                                                     .intValue();
        } catch (Exception e) {
            FacesUtils.addErrorMessage(e.getMessage());
        }

        // Calculate indices to be displayed in the ui.
        int endIndex = startRow + pageSize;

        if (endIndex > totalNumberCiudad) {
            endIndex = totalNumberCiudad;
        }

        try {
            ciudad = BusinessDelegatorView.findPageCiudad(sortColumnName,
                    sortAscending, startRow, endIndex - startRow);

            // Remove this Renderable from the existing render groups.
            //leaveRenderGroups();        			
        } catch (Exception e) {
            FacesUtils.addErrorMessage(e.getMessage());
        }

        // Add this Renderable to the new render groups.
        //joinRenderGroups();
        // Reset the dirtyData flag.
        onePageDataModel.setDirtyData(false);
        // This is required when using Hibernate.  If the SessionManager is not
        // cleared or closed objects are cached and stale objects will show up
        // in the table.
        // This way, the detached objects are reread from the database.
        // This call is not required with Hibernate, which uses a Query Hint
        // to clear the l2 cache in the DAO.
        flag = true;

        return new DataPage<Ciudad>(totalNumberCiudad, startRow, ciudad);
    }

    public DataModel getDataDTO() {
        state = PersistentFacesState.getInstance();

        if (onePageDataModel == null) {
            onePageDataModel = new LocalDataModelDTO(pageSize);
        }

        return onePageDataModel;
    }

    /**
    * This is where the Object data is retrieved from the database and
    * returned as a list of objects for display in the UI.
    */
    private DataPage<CiudadDTO> getDataPageDTO(int startRow, int pageSize) {
        // Retrieve the total number of objects from the database.  This
        // number is required by the DataPage object so the paginator will know
        // the relative location of the page data.
        int totalNumberCiudad = 0;

        try {
            totalNumberCiudad = BusinessDelegatorView.findTotalNumberCiudad()
                                                     .intValue();
        } catch (Exception e) {
            FacesUtils.addErrorMessage(e.getMessage());
        }

        // Calculate indices to be displayed in the ui.
        int endIndex = startRow + pageSize;

        if (endIndex > totalNumberCiudad) {
            endIndex = totalNumberCiudad;
        }

        try {
            ciudad = BusinessDelegatorView.findPageCiudad(sortColumnName,
                    sortAscending, startRow, endIndex - startRow);

            if (Utilities.validationsList(ciudad)) {
                ciudadDTO = new ArrayList<CiudadDTO>();

                for (Ciudad ciudadTmp : ciudad) {
                    CiudadDTO ciudadDTO2 = new CiudadDTO();
                    ciudadDTO2.setCiuCodigo(ciudadTmp.getCiuCodigo().toString());
                    ciudadDTO2.setCiuNombre((ciudadTmp.getCiuNombre() != null)
                        ? ciudadTmp.getCiuNombre().toString() : null);
                    ciudadDTO2.setEstCodigo_Estado((ciudadTmp.getEstado()
                                                             .getEstCodigo() != null)
                        ? ciudadTmp.getEstado().getEstCodigo().toString() : null);
                    ciudadDTO2.setPaiCodigo_Pais((ciudadTmp.getPais()
                                                           .getPaiCodigo() != null)
                        ? ciudadTmp.getPais().getPaiCodigo().toString() : null);
                    ciudadDTO2.setCiudad(ciudadTmp);
                    ciudadDTO2.setCiudadView(this);
                    ciudadDTO.add(ciudadDTO2);
                }
            }

            // Remove this Renderable from the existing render groups.
            leaveRenderGroups();
        } catch (Exception e) {
            FacesUtils.addErrorMessage(e.getMessage());
        }

        // Add this Renderable to the new render groups.
        joinRenderGroups();
        // Reset the dirtyData flag.
        onePageDataModel.setDirtyData(false);
        // This is required when using Hibernate.  If the SessionManager is not
        // cleared or closed objects are cached and stale objects will show up
        // in the table.
        // This way, the detached objects are reread from the database.
        // This call is not required with Hibernate, which uses a Query Hint
        // to clear the l2 cache in the DAO.
        flag = true;

        return new DataPage<CiudadDTO>(totalNumberCiudad, startRow, ciudadDTO);
    }

    protected boolean isDefaultAscending(String sortColumn) {
        return true;
    }

    /**
    * This method is called when a render call is made from the server. Render
    * calls are only made to views containing an updated record. The data is
    * marked as dirty to trigger a fetch of the updated record from the
    * database before rendering takes place.
    */
    public PersistentFacesState getState() {
        onePageDataModel.setDirtyData();

        return state;
    }

    /**
    * This method is called from faces-config.xml with each new session.
    */
    public void setRenderManager(RenderManager renderManager) {
        this.renderManager = renderManager;
    }

    public void renderingException(RenderingException arg0) {
        if (arg0 instanceof TransientRenderingException) {
        } else if (arg0 instanceof FatalRenderingException) {
            // Remove from existing Customer render groups.
            leaveRenderGroups();
        }
    }

    /**
    * Remove this Renderable from existing uiCustomerBeans render groups.
    * OnDemandRenderers are named/created using the underlying Customer Number.
    */
    private void leaveRenderGroups() {
        if (Utilities.validationsList(ciudadDTO)) {
            for (CiudadDTO ciudadTmp : ciudadDTO) {
                renderManager.getOnDemandRenderer("CiudadView").remove(this);
            }
        }
    }

    /**
    * Add this Renderable to the new uiCustomerBeans render groups.
    * OnDemandRenderers are named/created using the underlying Customer Number.
    */
    private void joinRenderGroups() {
        if (Utilities.validationsList(ciudadDTO)) {
            for (CiudadDTO ciudadTmp : ciudadDTO) {
                renderManager.getOnDemandRenderer("CiudadView").add(this);
            }
        }
    }

    public void dispose() throws Exception {
    }

    public RenderManager getRenderManager() {
        return renderManager;
    }

    public void setState(PersistentFacesState state) {
        this.state = state;
    }

    public HtmlInputText getTxtCiuNombre() {
        return txtCiuNombre;
    }

    public void setTxtCiuNombre(HtmlInputText txtCiuNombre) {
        this.txtCiuNombre = txtCiuNombre;
    }

    public HtmlInputText getTxtCiuCodigo() {
        return txtCiuCodigo;
    }

    public void setTxtCiuCodigo(HtmlInputText txtCiuCodigo) {
        this.txtCiuCodigo = txtCiuCodigo;
    }

    public HtmlCommandButton getBtnSave() {
        return btnSave;
    }

    public void setBtnSave(HtmlCommandButton btnSave) {
        this.btnSave = btnSave;
    }

    public HtmlCommandButton getBtnModify() {
        return btnModify;
    }

    public void setBtnModify(HtmlCommandButton btnModify) {
        this.btnModify = btnModify;
    }

    public HtmlCommandButton getBtnDelete() {
        return btnDelete;
    }

    public void setBtnDelete(HtmlCommandButton btnDelete) {
        this.btnDelete = btnDelete;
    }

    public HtmlCommandButton getBtnClear() {
        return btnClear;
    }

    public void setBtnClear(HtmlCommandButton btnClear) {
        this.btnClear = btnClear;
    }

    public void setRenderDataTable(boolean renderDataTable) {
        this.renderDataTable = renderDataTable;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }

    public List<CiudadDTO> getCiudadDTO() {
        return ciudadDTO;
    }

    public void setCiudadDTO(List<CiudadDTO> ciudadDTO) {
        this.ciudadDTO = ciudadDTO;
    }

    public TimeZone getTimeZone() {
        return java.util.TimeZone.getDefault();
    }
    
    public boolean isPopupPais() {
		return popupPais;
	}

	public void setPopupPais(boolean popupPais) {
		this.popupPais = popupPais;
	}

	public List<Pais> getList_paises(){		
		return list_paises;
	}

	public void setList_paises(List<Pais> listPaises) {
		list_paises = listPaises;
	}

	public HtmlInputText getTxtPaiNombre() {
		return txtPaiNombre;
	}

	public void setTxtPaiNombre(HtmlInputText txtPaiNombre) {
		this.txtPaiNombre = txtPaiNombre;
	}

	public HtmlInputText getTxtPaiNombreBusqueda() {
		return txtPaiNombreBusqueda;
	}

	public void setTxtPaiNombreBusqueda(HtmlInputText txtPaiNombreBusqueda) {
		this.txtPaiNombreBusqueda = txtPaiNombreBusqueda;
	}


	/**
    * A special type of JSF DataModel to allow a datatable and datapaginator
    * to page through a large set of data without having to hold the entire
    * set of data in memory at once.
    * Any time a managed bean wants to avoid holding an entire dataset,
    * the managed bean declares this inner class which extends PagedListDataModel
    * and implements the fetchData method. fetchData is called
    * as needed when the table requires data that isn't available in the
    * current data page held by this object.
    * This requires the managed bean (and in general the business
    * method that the managed bean uses) to provide the data wrapped in
    * a DataPage object that provides info on the full size of the dataset.
    */
    private class LocalDataModel extends PagedListDataModel {
        public LocalDataModel(int pageSize) {
            super(pageSize);
        }

        public DataPage<Ciudad> fetchPage(int startRow, int pageSize) {
            // call enclosing managed bean method to fetch the data
            return getDataPage(startRow, pageSize);
        }
    }

    private class LocalDataModelDTO extends PagedListDataModel {
        public LocalDataModelDTO(int pageSize) {
            super(pageSize);
        }

        public DataPage<CiudadDTO> fetchPage(int startRow, int pageSize) {
            // call enclosing managed bean method to fetch the data
            return getDataPageDTO(startRow, pageSize);
        }
    }
    
    public String action_buscarPaises() {
    	if(list_paises != null){
    		list_paises.clear();
    	}    	
    	action_popupVisible();
    	return "";
    }
    
    public void action_popupVisible(){
    	popupPais=!popupPais;
    }
     
    
    public String action_buscarPaiNombreParcial(){
    	try {
    		list_paises.clear();
			list_paises = BusinessDelegatorView.getPaisNombreParcial(txtPaiNombreBusqueda.getValue().toString().trim().toUpperCase());
		} catch (Exception e) {
			FacesUtils.addErrorMessage(e.getMessage());			
		}
    	return "";    	
    }
    
    public String action_cancelarBusqueda() {
		action_popupVisible();
		txtPaiNombreBusqueda.setValue("");
		txtPaiNombre.setValue("");
		return "";
	}
    
    public String action_terminarBusqueda() {
		action_popupVisible();
		txtPaiNombreBusqueda.setValue("");		
		return "";
	}
    
    
    public void action_seleccionPais(RowSelectorEvent e){
    	try {
		  txtPaiNombre.setValue(list_paises.get(e.getRow()).getPaiNombre());		  
		} catch (Exception e2) {
			FacesUtils.addErrorMessage(e2.getMessage());
			e2.printStackTrace();
		}
    }
    
}
